package com.jffccloud.common.util.crypto;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

public class Cryptor {
    public final static String ENC_MD2="MD2";
    public final static String ENC_MD5="MD5";
    public final static String ENC_SHA_1="SHA-1";
    public final static String ENC_SHA_256="SHA-256";
    public final static String ENC_SHA_384="SHA-384";
    public final static String ENC_SHA_512="SHA-512";

    public final static String ENC_HMAC_MD5="HmacMD5";
    public final static String ENC_HMAC_SHA1="HmacSHA1";
    public final static String ENC_HMAC_SHA256="HmacSHA256";
    public final static String ENC_HMAC_SHA384="HmacSHA384";
    public final static String ENC_HMAC_SHA512="HmacSHA512";

    private static List<String> mds = new ArrayList<String>() {{
        add(ENC_MD2);
        add(ENC_MD5);
    }};

    private static List<String> shas = new ArrayList<String>() {{
        add(ENC_SHA_1);
        add(ENC_SHA_256);
        add(ENC_SHA_384);
        add(ENC_SHA_512);
    }};

    private static List<String> macs = new ArrayList<String>() {{
        add(ENC_HMAC_MD5);
        add(ENC_HMAC_SHA1);
        add(ENC_HMAC_SHA256);
        add(ENC_HMAC_SHA384);
        add(ENC_HMAC_SHA512);
    }};

    public static String crypto(String algorithm, String message) {
        return crypto(algorithm, message, null);
    }

    public static String crypto(String algorithm, String message, String salt) {
        String result;
        if (macs.contains(algorithm)) {
            Mac mac = null;
            try {
                mac = Mac.getInstance(algorithm);
                if (salt != null && !salt.isEmpty()) {
                    SecretKeySpec signingKey = new SecretKeySpec(salt.getBytes(Charset.forName("UTF-8")), algorithm);
                    mac.init(signingKey);
                }
            } catch (GeneralSecurityException e) {
                throw new CryptoException(e.getMessage(), e);
            }
            result = Hex.encodeHexString(mac.doFinal(message.getBytes(Charset.forName("UTF-8"))));
        } else if (mds.contains(algorithm) || shas.contains(algorithm)) {
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance(algorithm);
            } catch (NoSuchAlgorithmException e) {
                throw new CryptoException(e.getMessage(), e);
            }

            if (salt != null && !salt.isEmpty()) {
                md.update(salt.getBytes(Charset.forName("UTF-8")));
            }
            result = Hex.encodeHexString(md.digest(message.getBytes()));
        } else {
            throw new CryptoException("Could not support this crypto's type " + algorithm + ".");
        }
        return result;
    }
}




